#include "widget3d.h"
#include <QDebug>

#define BUFFER_OFFSET(offset) ((void*) (offset))

Widget3D::Widget3D()
{
    setMinimumHeight(300);
}

Widget3D::~Widget3D()
{

}

void Widget3D::initializeGL()
{
    qInfo()<<"initializeGL";
    initializeOpenGLFunctions();

    //    glEnable(GL_TEXTURE_2D);

    m_program = new QOpenGLShaderProgram(this);

    m_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/triangles.vert");

    m_program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/triangles.frag");

    m_program->link();

    //VAO，VBO数据部分
    const GLfloat positions[] = {
         1.0f,  1.0f, -1.0f, 1.0f,
         1.0f, -1.0f, -1.0f, 1.0f,
        -1.0f,  1.0f, -1.0f, 1.0f,
        -1.0f, -1.0f, -1.0f, 1.0f,

        -1.0f,  1.0f,  1.0f, 1.0f,
        -1.0f, -1.0f,  1.0f, 1.0f,
         1.0f,  1.0f,  1.0f, 1.0f,
         1.0f, -1.0f,  1.0f, 1.0f,
    };

    const GLfloat colors[] = {
        1.0f, 1.0f, 1.0f, 1.0f,
        1.0f, 1.0f, 0.0f, 1.0f,
        1.0f, 0.0f, 1.0f, 1.0f,
        1.0f, 0.0f, 0.0f, 1.0f,

        0.0f, 1.0f, 1.0f, 1.0f,
        0.0f, 1.0f, 0.0f, 1.0f,
        0.0f, 0.0f, 1.0f, 1.0f,
        0.5f, 0.5f, 0.5f, 1.0f,
    };

    const GLushort indices[] = {
      0, 1, 2, 3, 4, 5, 6, 7,
      0xFFFF,
      4, 2, 6, 0, 7, 1, 5, 3
    };

    m_posAttr = m_program->attributeLocation("aPos");
    m_colorAttr = m_program->attributeLocation("aColor");

    glGenVertexArrays(1, m_VAO);
    glGenBuffers(1, m_VBO);
    glGenBuffers(1, m_EBO);

    glBindVertexArray(m_VAO[0]);
    glBindBuffer(GL_ARRAY_BUFFER, m_VBO[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(positions)+sizeof(colors), NULL, GL_STATIC_DRAW);

    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(positions), positions);
    glBufferSubData(GL_ARRAY_BUFFER, sizeof(positions), sizeof(colors), colors);

    glVertexAttribPointer(m_posAttr, 4, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), BUFFER_OFFSET(0));
    glVertexAttribPointer(m_colorAttr, 4, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), BUFFER_OFFSET(sizeof(positions)));

    glEnableVertexAttribArray(m_posAttr);
    glEnableVertexAttribArray(m_colorAttr);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_EBO[0]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void Widget3D::resizeGL(int w, int h)
{
    glViewport(0, 0, w, h);
}

void Widget3D::paintGL()
{
    //    qInfo()<<"paintGL";
    glClearColor(0.2f, 0.3f, 0.3f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    m_program->bind();

    float aspect = 1.0;
    QMatrix4x4 projection_matrix;
    projection_matrix.frustum(-1.0f, 1.0f, -aspect, aspect, 1.0f, 500.0f);
    m_program->setUniformValue("projection_matrix", projection_matrix);

    glBindVertexArray(m_VAO[0]);
#if USE_PRIMITIVE_RESTART
    glEnable(GL_PRIMITIVE_RESTART);
    glPrimitiveRestartIndex(0xFFFF);

    QMatrix4x4 model_matrix;
    model_matrix.translate(-2.0f, 0.0f, -5.0f);
    m_program->setUniformValue("model_matrix", model_matrix);
    glDrawElements(GL_TRIANGLE_STRIP, 17, GL_UNSIGNED_SHORT, 0);
#else
    QMatrix4x4 model_matrix;
    model_matrix.translate(-2.0f, 0.0f, -5.0f);
    m_program->setUniformValue("model_matrix", model_matrix);
    glDrawElements(GL_TRIANGLE_STRIP, 8, GL_UNSIGNED_SHORT, 0);

    QMatrix4x4 model_matrix2;
    model_matrix2.translate(2.0f, 0.0f, -5.0f);
    m_program->setUniformValue("model_matrix", model_matrix2);
    glDrawElements(GL_TRIANGLE_STRIP, 8, GL_UNSIGNED_SHORT, BUFFER_OFFSET(9*sizeof(GLushort)));
#endif

    m_program->release();
}
